#include "playlist.h"
#include "environment.h"


extern QString g_AppPath;


PlayList::PlayList(QObject *parent) :
    QObject(parent)
{
    //m_pMainWnd = parent;
    m_lastPlayList = 0;
    m_isUpdate = false;
    m_isCheckLcd = false;
    m_updateTimer = new QTimer(this);
    m_updateTimer->setSingleShot(true);
    connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateTimeOut()));

    m_playTimer = new QTimer(this);
    connect(m_playTimer, SIGNAL(timeout()), this, SLOT(timeToPlayNextList()));
}

PlayList::~PlayList()
{
    this->unLoad();
    clearList();
}

/*******************************************
  功能：加载数据库和资源文件路径，即在数据库中取出的为相对路径，
        加上资源文件的路径，构成绝对路径
  参数：
  返回值：
  ******************************************/
bool PlayList::Load(const QString &strListPath, const QString &resource)
{
  //  unLoad();

    if (m_db.isOpen())
    {
        m_db.closeDB();
    }
    m_resourceName = resource;
    m_db.setResourcePath(resource);
    return m_db.openDB(strListPath);
   // m_db.getCustomPlayPkgList();
}


/*******************************************
  功能：清除所有播放列表和关闭数据库
  参数：
  返回值：
  ******************************************/
void PlayList::unLoad()
{
    clearList();
    m_db.closeDB();
}


void PlayList::seekToTimePos(const float seconds, const int partitioinId)
{
    for(int i = 0; i < m_moduleList.count(); i++)
    {
        ModulePlay *modulePlay = m_moduleList.at(i);
        if (modulePlay->getCurPartitiionID() == partitioinId)
        {
            modulePlay->seekToTimePos(seconds);
            break;
        }
    }
}

void PlayList::getCurTimePos(const int partitioinId)
{
    for(int i = 0; i < m_moduleList.count(); i++)
    {
        ModulePlay *modulePlay = m_moduleList.at(i);
        if (modulePlay->getCurPartitiionID() == partitioinId)
        {
            modulePlay->getCurTimePos();
            break;
        }
    }
}

/*******************************************
  功能：更新当前列车的路线信息，然后从数据库中找出相对
        应的播放列表
  参数：routeMsg，列表路线信息
  返回值：
  ******************************************/
void PlayList::updateTranInfo(const RouteMsgStruct& routeMsg)
{
    if (!m_db.isOpen())
    {
        logger()->warn("Receive the TIS infomation, but dataBase not open, can't find the playlist");
        return;
    }

    //如果正在进行测试LCD或者正在更新那么播放数据不进行解析
    if (m_isCheckLcd || m_isUpdate)
        return;

//    qDebug() << "============updateTranInfoupdateTranInfoupdateTranInfo==========================";
    m_playTimer->stop();
    RouteMsgStruct route = routeMsg;
    m_usrPkgList.clear();
    ListItem list;
    int nRet = NOERR;

    //信号来时，先查找对应的car位置，如果没有查找对应的开门侧,这一侧(all platform side)/对侧(all non-platform side),
    //如果还是没有的话就查找所有位置(all position)
    try
    {
        route.positionIncar = route.positionIncar;
        nRet = m_db.getCustomPlayPkgList(m_usrPkgList, route);

        if(nRet != NOERR)
        {
           if(nRet != LOSTCONTENTWARIN)
           {
               //如果position不为0,那么查找对应的开端侧的内容
               if (route.positionIncar != 0)
               {
                   route.positionIncar = route.positionIncar % 2;  //lin 直接赋值过去给它
                   if (route.positionIncar == 0)
                       route.positionIncar = 2;
               }

               nRet = m_db.getCustomPlayPkgList(m_usrPkgList, route);
               if( (nRet != NOERR) && (nRet != LOSTCONTENTWARIN) )
               {
                   route.positionIncar = 0;     //All Position
                   nRet = m_db.getCustomPlayPkgList(m_usrPkgList, route);
               }
           }

        }
    }
    catch(...)
    {

    }


    //取得当前线路的默认播放内容，防止自定义播放列表无内容时可以播放
    m_nUsrCur = 0;
    m_nDefautlCur = 0;
    this->getDefaultList(list, route);
//    qDebug() << "................." << m_usrPkgList.count() << m_defaultPkgList.count();

    if((nRet == NOERR || nRet == LOSTCONTENTWARIN) && m_usrPkgList.count() != 0)
    {
        parseList(m_usrPkgList.at(m_nUsrCur));
        m_lastPlayList = 1;
    }
    else
    {
        parseList(list);
        m_nDefautlCur++;
    }

}

/*******************************************
  功能：更新当前列车的路线信息，然后从数据库中找出相对
        应的播放列表，在CE中使用
  参数：routeMsg，列表路线信息
  返回值：
  ******************************************/
void PlayList::updateCeTranInfo(const CeRouteMsg& routeMsg)
{    
    if (!m_db.isOpen())
    {
        logger()->warn("Receive the TIS infomation, but dataBase not open, can't find the playlist");
        return;
    }

    //如果正在进行测试LCD或者正在更新那么播放数据不进行解析
    if (m_isCheckLcd || m_isUpdate)
        return;

    m_playTimer->stop();
    CeRouteMsg route = routeMsg;
    m_usrPkgList.clear();
    ListItem list;
    int nRet = NOERR;

    //信号来时，先查找对应的car位置，如果没有查找对应的开门侧,这一侧(all platform side)/对侧(all non-platform side),
    //如果还是没有的话就查找所有位置(all position)
    try
    {
        route.positionIncar = route.positionIncar;
        nRet = m_db.getCePlayPkgList(m_usrPkgList, route);

        if(nRet != NOERR)
        {
           if(nRet != LOSTCONTENTWARIN)
           {
               //如果position不为0,那么查找对应的开端侧的内容
               if (route.positionIncar != 0)
               {
                   route.positionIncar = route.positionIncar % 2;  //lin 直接赋值过去给它
                   if (route.positionIncar == 0)
                       route.positionIncar = 2;
               }

               nRet = m_db.getCePlayPkgList(m_usrPkgList, route);
               if( (nRet != NOERR) && (nRet != LOSTCONTENTWARIN) )
               {
                   route.positionIncar = 0;     //All Position
                   nRet = m_db.getCePlayPkgList(m_usrPkgList, route);
               }
           }

        }
    }
    catch(...)
    {

    }


    m_nUsrCur = 0;
    m_nDefautlCur = 0;
    this->getCeDefaultList(list, route);

    if(nRet == NOERR || nRet == LOSTCONTENTWARIN)
    {
        parseList(m_usrPkgList.at(m_nUsrCur));
        m_lastPlayList = 1;
    }
    else
    {
        parseList(list);
        m_nDefautlCur++;
        m_lastPlayList = 2;
    }
}

//更新状态,state为0时开始更新,state=1时为更新完成
void PlayList::updateDataState(const int state, const QString &msg)
{
//    qDebug() << "===============<<< updateDataState >>>===================" << msg;

    ModulePlay* modulePlay;
    if (m_moduleList.count() == 0)
    {
        modulePlay = new ModulePlay(this->parent());
    } else {
        modulePlay = m_moduleList.at(0);
    }

    if (state == 0)
    {
        modulePlay->startToUpdata(msg);
    } else {
        modulePlay->updateDataState(msg);
    }

    for(int i = 1; i < m_moduleList.count(); i++)
    {
        ModulePlay* modulePlay = m_moduleList.at(i);
        modulePlay->hide();
    }

    if (state >= 1)
    {
        m_updateTimer->start(1 * 1000);
    } else if (state <= 0)
    {
        m_isUpdate = true;
    }
}


//播放开机信息
void PlayList::playInfomation(const int second, const QString &msg)
{
    int time = second;
    if (time <= 0)
    {
        return;
    }
    ModulePlay* modulePlay;

    if (m_moduleList.count() == 0)
    {
        modulePlay = new ModulePlay(this->parent());
    } else {
        modulePlay = m_moduleList.at(0);
    }

    for(int i = 1; i < m_moduleList.count(); i++)
    {
        ModulePlay* modulePlay = m_moduleList.at(i);
        modulePlay->hide();
    }
    modulePlay->updateDataState(msg);
    m_playTimer->start(time * 1000);

}

/*******************************************
  功能：检测LCD屏
  参数：cmd,命令；
    0x50 开始为发送测试LCD屏模块
    0x5F 开启测试模式
    0x5E 关闭测试模式
    0x51 红色背景
    0x52 绿色背景
    0x53 蓝色背景
    0x54 白色背景
    0x55 文字背景
  返回值：得到播放包列表
  ******************************************/
void PlayList::chcekLcd(const qint8 cmd)
{
//    qDebug() << "chcekLcd====================>" << cmd;
    QList<RoutePkgList> list;

    RoutePkgList routePkgList;
    RoutePkgStruct routePkg;


    LayoutStruct layoutStruct;               //布局结构体
    QList<ContentStruct > cntlist;

    ContentStruct cnt;
    cnt.contentID = 1;
    cnt.order = 1;
    cnt.duration = 60 * 60 * 24;
    cnt.isHolidayContent = false;
    cnt.repeatFlag = 1;
    cnt.isUnlimited = true;

    layoutStruct.layoutID = 1;
    layoutStruct.partitionID = 1;
    layoutStruct.x = 0;
    layoutStruct.y = 0;
    layoutStruct.height = GLOBAL_RESOLUTION_HEIGHT;
    layoutStruct.width = GLOBAL_RESOLUTION_WIDTH;

    switch(cmd)
    {
    case 0x5F:
        m_isCheckLcd = true;
        return;
        break;
    case 0x5E:
        m_isCheckLcd = false;
        return;
        break;
    case 0x55:
        cnt.contentTypeID = CONTENT_OnlyShowTxt;
        cnt.contentFile = tr("%1/txt").arg(TESTLCDPATH);;
        break;
    case 0x54:
        cnt.contentTypeID = CONTENT_PIC;
        cnt.contentFile = tr("%1/white.png").arg(TESTLCDPATH);
        break;
    case 0x53:
        cnt.contentTypeID = CONTENT_PIC;
        cnt.contentFile = tr("%1/blue.png").arg(TESTLCDPATH);;
        break;
    case 0x52:
        cnt.contentTypeID = CONTENT_PIC;
        cnt.contentFile = tr("%1/green.png").arg(TESTLCDPATH);;
        break;
    case 0x51:
        cnt.contentTypeID = CONTENT_PIC;
        cnt.contentFile = tr("%1/red.png").arg(TESTLCDPATH);;
        break;
    }

    cntlist.append(cnt);

    routePkg.contentStructList = cntlist;
    routePkg.layoutStruct = layoutStruct;

    routePkgList.playTime = 60 * 60 * 24;
    routePkgList.routePkgList.append(routePkg);

    list.append(routePkgList);

    if (list.count() != 0)
        this->parseList(list.at(0));
}


/*******************************************
  功能：清除列表，如果播放完成，那么将列表全部清除
  参数：
  返回值：
  ******************************************/
void PlayList::clearList()
{

    for(int i = 0; i < m_moduleList.count(); i++)
    {
        ModulePlay* modulePlay = m_moduleList.at(i);
       if (modulePlay != NULL)
       {
           delete modulePlay;
       }
    }
    m_moduleList.clear();

    for(int i=0; i<m_picList.count(); i++)
    {
        PixPlayLabel* pic =  m_picList.at(i);
        if(pic != NULL)
        {
            pic->stop();
            pic->hide();
            delete pic;
//            delete
        }
    }
    m_picList.clear();

    for(int i=0; i<m_mediaList.count(); i++)
    {
        medialist* media =  m_mediaList.at(i);
        if(media != NULL)
        {
            //media->stop();
            delete media;
        }

    }
    m_mediaList.clear();

    for(int i=0; i<m_bulletinList.count(); i++)
    {
        bulletinlist* bulletin =  m_bulletinList.at(i);
        if(bulletin != NULL)
        {
           // bulletin->stop();
            delete bulletin;
        }

    }
    m_bulletinList.clear();
}

void PlayList::parseList(const ListItem &list)
{

    //如果进行更新中,那么即使TIS有信号过来也不进行反应
    if (m_isUpdate)
    {
        return;
    }

    //当分区的播放内容结束时，从此列表中删除分区号，当所有分区都播放完时，开始播放默认包
    m_partitionIDList.clear();

    if (list.routePkgList.isEmpty())
    {
        this->timeToPlayNextList();
        return;
    }

    //当前布局的播放时间，如果有多重布局播放要添加此
    //用户自定义的表是根据设定布局时间来确定几时播放下一个播放包，而默认包则是全部播放完成则播放下一个包
    if (list.playTime <= 0)
    {
        m_playTimer->start(3 * 1000);
    } else {
        m_playTimer->start(list.playTime * 1000);
    }

    //此方法为每次信号改变时不删除前一次的modulePlay,直接更新他们的内容,
    //此方法可以减少重新new modulePlay的时间
    int i = 0;
    bool moduleListHasEnd = false;
    //开始解析每一个播放布局，每个播放布局包含n个播放模块，如文字显示，视频播放都为一个模块
    //各个模块有各自的播放内容和列表
    for(i = 0; i < list.routePkgList.count(); i++)
    {
        ModulePlay* modulePlay;
        if (i < m_moduleList.count() && !moduleListHasEnd)
        {
            modulePlay = m_moduleList.at(i);
        } else {
            moduleListHasEnd = true;
            modulePlay = new ModulePlay(this->parent());
            connect(modulePlay, SIGNAL(mplayerTimePos(float,int)), this, SIGNAL(mplayerTimePos(float,int)));
            connect(modulePlay, SIGNAL(playAllFinish(int)), this, SLOT(partitionPlayFinish(int)));
            connect(this, SIGNAL(updateConfig()), modulePlay, SLOT(updateConfig()));

            m_moduleList.append(modulePlay);
        }

        modulePlay->updateRoutePkg(list.routePkgList.at(i));
        m_partitionIDList.append(list.routePkgList.at(i).layoutStruct.partitionID);
        modulePlay->play();
    }


    //其余没有用到播放模块进行相应的隐藏
    if (i < m_moduleList.count())
    {
        for(int j = i; j < m_moduleList.count(); j++)
        {
            ModulePlay* modulePlay = m_moduleList.at(j);
            modulePlay->hide();
        }
    }
    return;

    //下面再使用！！

    //此方法为每次信号改变时将之前的modulePlay删除,此方法第一次信号转化会在new modulePlay时花费一定的时间
    if(list.routePkgList.isEmpty())
    {
        return;
    }

    clearList();    //ivan @2011.10.10 add
    //========================================== lin
    for(int i = 0; i < list.routePkgList.count(); i++)
    {
        ModulePlay* modulePlay = new ModulePlay(this->parent());
        connect(this, SIGNAL(updateConfig()), modulePlay, SLOT(updateConfig()));

        if (modulePlay != NULL)
        {
            m_moduleList.append(modulePlay);
            modulePlay->updateRoutePkg(list.routePkgList.at(i));
            modulePlay->play();
        }

    }
    return;
    //===================================


    //ivan写的播放方式,不完整,只能每一次播放一样,而且每次都将重新new 播放模块
    for(int i=0; i<list.routePkgList.count(); i++)
    {
        //switch(list[i].contentTypeID)           //at()操作比操作符[]更快，因为它不需要深度复制(deep copy)。
        switch(list.routePkgList.at(i).contentTypeID)
        {
        case CONTENT_MEDIA:
        {
            int nIndex = m_mediaList.count();
            medialist* media = new medialist(nIndex, /*m_pMainWnd*/this->parent());  //这个指针应该保存便于以后操作及释放
            if(media != NULL)
            {
                m_mediaList.append(media);
                media->updateList(list.routePkgList.at(i));
            }

            break;
        }

        case CONTENT_PIC:
        {
            int nIndex = m_picList.count();
            PixPlayLabel* pic = new PixPlayLabel(nIndex, (QWidget*)this->parent());  //这个指针应该保存便于以后操作及释放
            if(pic != NULL)
            {
                m_picList.append(pic);

                pic->setGeometry(list.routePkgList.at(i).layoutStruct.x,
                                 list.routePkgList.at(i).layoutStruct.y,
                                 list.routePkgList.at(i).layoutStruct.width,
                                 list.routePkgList.at(i).layoutStruct.height);

                pic->updatePlayCntList(list.routePkgList.at(i).contentStructList);

                pic->show();
                pic->start();
            }

            break;
        }

        case CONTENT_TEXT:
        {
            int nIndex = m_bulletinList.count();
            bulletinlist* bulletin = new bulletinlist(nIndex, this->parent());  //这个指针应该保存便于以后操作及释放
            if(bulletin != NULL)
            {
                m_bulletinList.append(bulletin);
                bulletin->updateList(list.routePkgList.at(i));
            }
            break;
        }
        }
    }
}

void PlayList::getDefaultList(ListItem& list, const RouteMsgStruct& routeMsg)
{
    RouteMsgStruct route = routeMsg;
    ListItem  defaultList;
    m_defaultPkgList.clear();

    int nRet = NOERR;
    try
    {
        nRet = m_db.getDefaultPlayPkgList(m_defaultPkgList, route);
        if(nRet != NOERR)
        {
           if(nRet != LOSTCONTENTWARIN)
           {
               route.positionIncar = 2 - (route.positionIncar % 2);
               nRet = m_db.getDefaultPlayPkgList(m_defaultPkgList, route);
//               qDebug() << "routeMsg====" << routeMsg.routeCode;
               if( (nRet != NOERR) && (nRet != LOSTCONTENTWARIN) )
               {
                   route.positionIncar = 0;     //All Position
                   nRet = m_db.getDefaultPlayPkgList(m_defaultPkgList, route);
               }
           }

        }
    }
    catch(...)
    {

    }

    if (m_defaultPkgList.count() > 0)
    {
        list = m_defaultPkgList.at(m_nDefautlCur);
    }

}

void PlayList::getCeDefaultList(ListItem& list, const CeRouteMsg& routeMsg)
{
    CeRouteMsg route = routeMsg;
    m_defaultPkgList.clear();

    int nRet = NOERR;
    try
    {
        nRet = m_db.getCeDefaultPlayPkgList(m_defaultPkgList, route);
        if(nRet != NOERR)
        {
           if(nRet != LOSTCONTENTWARIN)
           {
               route.positionIncar = 2 - (route.positionIncar % 2);
               nRet = m_db.getCeDefaultPlayPkgList(m_defaultPkgList, route);
               if( (nRet != NOERR) && (nRet != LOSTCONTENTWARIN) )
               {
                   route.positionIncar = 0;     //All Position
                   nRet = m_db.getCeDefaultPlayPkgList(m_defaultPkgList, route);
               }
           }

        }
    }
    catch(...)
    {

    }

    if (m_defaultPkgList.count() > 0)
    {
        list = m_defaultPkgList.at(m_nDefautlCur);
    }
}

void PlayList::updateTimeOut()
{
    m_isUpdate = false;
}


void PlayList::partitionPlayFinish(const int partitionID)
{
    //当分区的播放内容结束时，从此列表中删除分区号，当所有分区都播放完时，开始播放默认包
//    if (m_isPlayDefault)
//    {
//        m_partitionIDList.removeOne(partitionID);

//        if (m_partitionIDList.count() <= 0)
//        {
//            this->timeToPlayNextList();
//        }
//    }
}

//当前布局播放完成，开始播放下一个布局
void PlayList::timeToPlayNextList()
{
     ListItem list;

    //如果进行更新中,那么即使TIS有信号过来也不进行反应
    if (m_isUpdate)
    {
        return;
    }

    //如果播放完配置列表，那么播放默认列表(defaultlist)
    if (m_nUsrCur < (m_usrPkgList.count() - 1))
    {
        m_nUsrCur ++;
        list = m_usrPkgList.at(m_nUsrCur);

        if (list.playTime <= 0)
        {
            list.playTime = 3;
        }

        m_playTimer->start(list.playTime * 1000);
    } else {
        m_playTimer->stop();
        if (m_nDefautlCur >= m_defaultPkgList.count())
        {
            m_nDefautlCur = 0;
        }

        if (m_defaultPkgList.count() < 1)
        {
            return;
        }
        list = m_defaultPkgList.at(m_nDefautlCur);

        m_nDefautlCur++;

        if (list.playTime <= 0)
        {
            list.playTime = 3;
        }

        m_playTimer->start(list.playTime * 1000);
    }
    //此方法为每次信号改变时不删除前一次的modulePlay,
    //直接更新他们的内容,此方法可以减少重新new modulePlay的时间
    bool moduleListHasEnd = false;
    int i = 0;

    //开始一个播放布局的解析，拆分为几个模块，各个模块有各自的播放内容和列表
    for(i = 0; i < list.routePkgList.count(); i++)
    {
        ModulePlay* modulePlay;
        if (i < m_moduleList.count() && !moduleListHasEnd)
        {
            modulePlay = m_moduleList.at(i);
        } else {
            moduleListHasEnd = true;

            modulePlay = new ModulePlay(this->parent());
            connect(modulePlay, SIGNAL(mplayerTimePos(float,int)), this, SIGNAL(mplayerTimePos(float,int)));
            connect(this, SIGNAL(updateConfig()), modulePlay, SLOT(updateConfig()));

            m_moduleList.append(modulePlay);
        }

        modulePlay->updateRoutePkg(list.routePkgList.at(i));
        modulePlay->play();
    }


    if (i < m_moduleList.count())
    {
        for(int j = i; j < m_moduleList.count(); j++)
        {
//            qDebug() << m_moduleList.count() << "j===" << j;
            ModulePlay* modulePlay = m_moduleList.at(j);
            modulePlay->hide();
        }
    }

    return;
}
